<template>
    <div id="container">
        <div class="absolute top-6 left-30 z-1">
            <vxe-button type="primary" @click="getGraphData">获取数据</vxe-button>
            <vxe-button type="primary" @click="addNode">添加节点</vxe-button>
            <vxe-button type="primary" @click="getElement">获取元素</vxe-button>
            <vxe-button type="primary" @click="updateAttributes">更新属性</vxe-button>
        </div>
        <!-- 用于显示 LogicFlow 图表的容器 -->
        <div id="divlf"></div>
        <UserDrawer ref="editRef" />
        <input ref="fileInput" type="file" accept=".json" @change="handleFileChange" style="display: none">
        <vxe-modal v-model="showPopup" :width="600" :height="400">
            <CodeEditor v-model:code="code" lang="json" />
        </vxe-modal>
    </div>
</template>

<script setup lang="ts">
import { onMounted, ref, ComponentInstance } from 'vue'
import LogicFlow from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { Control, Snapshot, DndPanel, SelectionSelect, Menu } from '@logicflow/extension'
import '@logicflow/extension/lib/style/index.css'
// 导入代码编辑器组件
import CodeEditor from '@/components/CodeEditor.vue'

// 导入自定义的图形节点组件
import UserTask from './components/CustomNode/UserTask'
import ServiceTask from './components/CustomNode/ServiceTask'
import StartEvent from './components/CustomNode/StartEvent'
import EndEvent from './components/CustomNode/EndEvent'
import Gateway from './components/CustomNode/Gateway'

import UserDrawer from './components/PropertySetting/UserDrawer.vue'

const showPopup = ref(false)
const code = ref('')

const fileInput = ref(null)
const lfRef = ref<LogicFlow>()
const editRef = ref<ComponentInstance<typeof UserDrawer>>()

// 定义图表数据，包含节点和边
const data = {
    nodes: [
        {
            id: '1',
            type: 'StartEvent', // 节点类型为矩形
            x: 200, // 节点的 x 坐标
            y: 100, // 节点的 y 坐标
            text: '节点1' // 节点显示的文本
        },
        {
            id: '2',
            type: 'UserTask', // 节点类型为圆形
            x: 400, // 节点的 x 坐标
            y: 100, // 节点的 y 坐标
            text: '节点2', // 节点显示的文本
            properties: {
                refY: 4
            }
        },
        {
            id: '3',
            type: 'EndEvent', // 节点类型为圆形
            x: 600, // 节点的 x 坐标
            y: 100, // 节点的 y 坐标
            text: '节点3' // 节点显示的文本
        }
    ],
    edges: [
        {
            id: 'line_1',
            sourceNodeId: '1', // 起始节点的 ID
            targetNodeId: '2', // 目标节点的 ID
            type: 'polyline', // 边的类型为折线
            text: '连线' // 边显示的文本           
        },
        {
            id: 'line_2',
            sourceNodeId: '2', // 起始节点的 ID
            targetNodeId: '3', // 目标节点的 ID
            type: 'polyline', // 边的类型为折线
            text: '连线' // 边显示的文本           
        }
    ]
}

// 在组件挂载时执行
onMounted(() => {
    // 创建 LogicFlow 实例
    const lf = new LogicFlow({
        container: document.getElementById('divlf')!, // 指定容器元素
        plugins: [DndPanel, SelectionSelect, Control, Snapshot, Menu],
        grid: true // 启用网格
    })

    // 注册自定义节点
    lf.register(UserTask)
    lf.register(ServiceTask)
    lf.register(StartEvent)
    lf.register(EndEvent)
    lf.register(Gateway)


    // 为控制面板追加按钮（必须在 lf.render() 之前设置）
    lf.extension.control.addItem({
        iconClass: 'lf-control-clear',
        text: '清空',
        title: '清空',
        size: 'medium',
        onClick: () => {
            lf.clearData()
        }
    })
    lf.extension.control.addItem({
        iconClass: 'lf-control-import',
        text: '导入',
        title: '导入',
        size: 'medium',
        onClick: () => {
            fileInput.value.click();
        }
    })
    lf.extension.control.addItem({
        iconClass: 'lf-control-export',
        text: '导出',
        title: '导出',
        size: 'medium',
        onClick: () => {
            const graphData = lf.getGraphRawData()
            //console.log('graphData --->>>', JSON.stringify(graphData))
            download('流程图.json', JSON.stringify(graphData))
        }
    })
    lf.extension.control.addItem({
        iconClass: 'lf-control-download',
        text: '下载图片',
        title: '下载图片',
        size: 'medium',
        onClick: () => {
            // 禁用全局CSS规则
            lf.extension.snapshot.useGlobalRules = false;
            lf.getSnapshot('流程图.png');
        }
    })

    // 设置拖拽面板的节点数据（必须在 lf.render() 之前设置）
    lf.extension.dndPanel.setPatternItems([
        {
            label: '选区',
            className: 'custom-selection',
            icon: '',
            callback: () => {
                lf.openSelectionSelect()
                lf.once('selection:selected', () => {
                    lf.closeSelectionSelect()
                })
            }
        },
        {
            type: 'StartEvent',
            text: '开始',
            label: '开始节点',
            icon: ''
        },
        {
            type: 'UserTask',
            text: '用户任务',
            label: '用户任务',
            icon: '',
            className: 'important-node'
        },
        {
            type: 'ServiceTask',
            text: '系统任务',
            label: '系统任务',
            icon: '',
            className: 'import_icon'
        },
        {
            type: 'Gateway',
            text: '条件判断',
            label: '条件判断',
            icon: ''
        },
        {
            type: 'EndEvent',
            text: '结束',
            label: '结束节点',
            icon: ''
        }
    ])

    // 渲染图表数据
    lf.render(data)

    lf.on('node:dbclick', (data) => {
        console.log(data)
        editRef.value?.add()
    })
    lf.on('node:dnd-add', (data) => {
        console.log(data)
        return false
    })
    // 保存 lf 实例
    lfRef.value = lf
})

// 下载文件
const download = (filename: string, text: string) => {
    const element = document.createElement('a');
    element.setAttribute(
        'href',
        'data:text/plain;charset=utf-8,' + encodeURIComponent(text),
    );
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();
    document.body.removeChild(element);
};

// 处理文件读取
const handleFileChange = (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.onload = (event) => {
        const xml = event.target?.result;
        lfRef.value?.render({ nodes: JSON.parse(xml as string).nodes, edges: JSON.parse(xml as string).edges });
    };
    reader.onerror = (error) => console.log(error);

    file && reader.readAsText(file);
}



const getGraphData = () => {
    const graphData = lfRef.value?.getGraphData()
    console.log('graphData:', JSON.stringify(graphData))
    //
    code.value = JSON.stringify(graphData,null,2)
    showPopup.value = true

    const getGraphRawData = lfRef.value?.getGraphRawData()
    console.log('getGraphRawData:', JSON.stringify(getGraphRawData))
}
const addNode = () => {
    lfRef.value?.addNode({
        type: 'circle',
        x: 200,
        y: 300,
        text: '圆形节点'
    })
}
const getElement = () => {
    const element = lfRef.value?.graphModel.getElement('2')
    console.log('element:', element)
}
const updateAttributes = () => {
    const graphModel = lfRef.value?.graphModel
    graphModel?.updateAttributes('1', {
        radius: 8
    })
    graphModel?.updateText('1', 'hello world')
    graphModel?.changeNodeType('1', 'UserTask')
    graphModel?.setTheme({
        rect: {
            fill: 'red'
        }
    })

    const node2 = graphModel?.getNodeModelById('2')
    node2?.setStyles({
        fill: 'green',
        stroke: '#666'
    })
    graphModel?.updateAttributes('2', {
        r: 40
    })

    graphModel?.updateAttributes('line_1', {
        isAnimation: true
    })

    const edgeModel = graphModel?.getEdgeModelById('line_1')
    const properties = edgeModel?.getProperties()
    console.log('properties:', properties)
    // edgeModel?.setProperties({
    //   // 自定义properties
    //   text: '动画节点'
    // })
}
</script>

<style>
#container,
#divlf {
    width: 100%;
    height: 100%;
}

.lf-control-clear {
    background-image: url('');
}

.lf-control-import {
    background-image: url('');
}

.lf-control-export {
    background-image: url('');
}

.lf-control-download {
    background-image: url('');
}
</style>
